﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;
using CardsServer.Tools;
using CardsServer.DAL;
namespace CardsServer
{
    public class XmppSeverConnection
    {
        private static string connStr = MyConfig.getConnection().connstr;
        DAL.DataClassesDataContext ctx = new DAL.DataClassesDataContext(connStr);
        private CardsServer.Main frm;
        public List<View_user_dep> alluser { get; set; }
        #region << Constructors >>
        public XmppSeverConnection()
        {
            streamParser = new StreamParser();
            streamParser.OnStreamStart += new StreamHandler(streamParser_OnStreamStart);
            streamParser.OnStreamEnd += new StreamHandler(streamParser_OnStreamEnd);
            streamParser.OnStreamElement += new StreamHandler(streamParser_OnStreamElement);

        }

        public XmppSeverConnection(GDJ.Foundtion.Server.Main a, Socket sock)
            : this()
        {


            alluser = ctx.View_user_dep.ToList();
            frm = a;
            m_Sock = sock;

            m_Sock.BeginReceive(buffer, 0, BUFFERSIZE, 0, new AsyncCallback(ReadCallback), null);
        }
        #endregion

        #region 变量定义
        private StreamParser streamParser;
        public Socket m_Sock;
        private const int BUFFERSIZE = 1024;
        private byte[] buffer = new byte[BUFFERSIZE];
        public Jid jid;
        public delegate void mydelegate(string str);

        /// <summary>
        /// 所有用户
        /// </summary>

        /// <summary>
        /// 所有部门
        /// </summary>
        public List<PW_Department> allDepartment { get; set; }

        #endregion

        public void ReadCallback(IAsyncResult ar)
        {
            try
            {
                int bytesRead = m_Sock.EndReceive(ar);

                if (bytesRead > 0)
                {
                    streamParser.Push(buffer, 0, bytesRead);

                    m_Sock.BeginReceive(buffer, 0, BUFFERSIZE, 0, new AsyncCallback(ReadCallback), null);
                }
                else
                {
                    m_Sock.Shutdown(SocketShutdown.Both);
                    m_Sock.Close();
                }
            }
            catch
            {
                deluser();
            }
        }

        public void Send(string data)
        {
            try
            {
                byte[] byteData = Encoding.UTF8.GetBytes(data);
                frm.BeginInvoke(new mydelegate(frm.ShowSendMessage), new Object[] { data });
                //发送数据给客户端
                m_Sock.BeginSend(byteData, 0, byteData.Length, 0, new AsyncCallback(SendCallback), null);
            }
            catch (Exception e)
            {
                frm.BeginInvoke(new mydelegate(frm.writeRTBmessage), new Object[] { e.ToString() });
            }
        }

        public void SendCallback(IAsyncResult ar)
        {
            try
            {
                int bytesSent = m_Sock.EndSend(ar);
                Console.WriteLine("Sent {0} bytes to client.", bytesSent);

            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }
        }

        public void Stop()
        {
            Send("</stream:stream>");
            m_Sock.Shutdown(SocketShutdown.Both);
            m_Sock.Close();
        }

        #region << Properties and Member Variables >>
        //		private int			m_Port			= 5222;		
        private string m_SessionId = null;

        public string SessionId
        {
            get
            {
                return m_SessionId;
            }
            set
            {
                m_SessionId = value;
            }
        }
        #endregion

        private void streamParser_OnStreamStart(object sender, Node e)
        {
            SendOpenStream();
        }

        private void streamParser_OnStreamEnd(object sender, Node e)
        {
            deluser();
        }

        private void deluser()
        {
            if (Online.onlineuser.Count(p => p.jid.User == jid.User) == 1)
            {
                try
                {
                    frm.listViewOnlineUser.Items.Remove(frm.listViewOnlineUser.FindItemWithText(jid.User));
                    XmppSeverConnection con = Online.onlineuser.Single(p => p.jid.User == jid.User);
                    Online.onlineuser.Remove(con);
                }
                catch (Exception ex)
                {
                    frm.richTextBox2.Text += ex.Message;
                }
                Presence pre;
                pre = new Presence();
                pre.Type = PresenceType.unavailable;
                pre.From = jid;
                try
                {
                    foreach (XmppSeverConnection conn in Online.onlineuser)
                    {
                        conn.Send(pre);
                    }
                }
                catch
                { }
            }
        }

        private void streamParser_OnStreamElement(object sender, Node e)
        {
            frm.BeginInvoke(new mydelegate(frm.ShowRecvMessage), new Object[] { e.ToString() });
            Console.WriteLine("OnStreamElement: " + e.ToString());

            #region 处理出席消息
            if (e.GetType() == typeof(Presence))
            {
                Presence pres = e as Presence;

                //处理会议室被取消消息
                if (pres.Type == PresenceType.invisible)
                {
                    foreach (Meeting meeting in Online.onlinemeeting)
                    {
                        if (meeting.jid.Equals(pres.To))
                        {
                            if (this.jid.User == pres.To.Resource)
                            {
                                Online.onlinemeeting.Remove(meeting);
                                pres.From = pres.To;
                                foreach (XmppSeverConnection con in Online.onlineuser)
                                {
                                    pres.To = con.jid;
                                    con.Send(pres);
                                }
                                break;
                            }
                        }
                    }
                }
                //处理用户上线消息
                if (pres.Show == ShowType.chat)
                {
                    pres.From = this.jid;
                    foreach (XmppSeverConnection con in Online.onlineuser)
                    {
                        if (con.jid.User != this.jid.User)
                        {
                            pres.To = con.jid;
                            con.Send(pres);
                        }
                    }
                }
                //处理用户退出会议消息
                if (pres.Type == PresenceType.unsubscribe)
                {
                    foreach (Meeting meeting in Online.onlinemeeting)
                    {
                        if (pres.To.Equals(meeting.jid))
                        {
                            meeting.userinmeeting.Remove(this.jid);
                            pres.From = this.jid;
                            foreach (Jid jd2 in meeting.userinmeeting)
                            {
                                foreach (XmppSeverConnection con in Online.onlineuser)
                                {
                                    if (jd2.Equals(con.jid))
                                    {
                                        con.Send(pres);
                                        break;
                                    }
                                }
                            }
                            break;
                        }
                    }
                }
            }
            #endregion

            #region 路由Message
            else if (e.GetType() == typeof(agsXMPP.protocol.client.Message))
            {
                agsXMPP.protocol.client.Message msg = e as agsXMPP.protocol.client.Message;
                //路由点对点聊天消息
                if (msg.Type == MessageType.chat)
                {
                    foreach (XmppSeverConnection con in Online.onlineuser)
                    {
                        if (con.jid.User == msg.To.User)
                        {
                            msg.From = jid;
                            con.Send(msg);
                        }
                    }
                }
                //路由群聊消息
                if (msg.Type == MessageType.groupchat)
                {
                    foreach (Meeting meeting in Online.onlinemeeting)
                    {
                        if (msg.To.Equals(meeting.jid))
                        {
                            msg.From = this.jid;
                            foreach (Jid jd2 in meeting.userinmeeting)
                            {
                                foreach (XmppSeverConnection con in Online.onlineuser)
                                {
                                    if (jd2.Equals(con.jid))
                                    {
                                        con.Send(msg);
                                        break;
                                    }
                                }
                            }
                            break;
                        }
                    }
                }

                //绘图信息
                if (msg.Type == MessageType.headline)
                {
                    foreach (Meeting meeting in Online.onlinemeeting)
                    {
                        if (msg.To.Equals(meeting.jid))
                        {
                            msg.From = this.jid;
                            foreach (Jid jd2 in meeting.userinmeeting)
                            {
                                foreach (XmppSeverConnection con in Online.onlineuser)
                                {
                                    if (jd2.Equals(con.jid))
                                    {
                                        con.Send(msg);
                                        break;
                                    }
                                }
                            }
                            break;
                        }
                    }
                }
            }
            #endregion

            #region 处理IQ消息
            else if (e.GetType() == typeof(IQ))
            {
                ProcessIQ(e as IQ);
            }
            #endregion
        }

        private void ProcessIQ(IQ iq)
        {
            #region 好友信息查询
            if (iq.HasTag(typeof(Info)))
            {
                if (iq.Type == IqType.get)
                {
                    Info _Info = iq.SelectSingleElement(typeof(Info)) as Info;
                    View_user_dep user = alluser.Single(p => p.UserNo == _Info.Userno);
                    iq.SwitchDirection();
                    iq.Type = IqType.result;
                    _Info.Department = user.Depname;
                    _Info.Tel = user.Mobilephone;
                    _Info.Nation = user.Nation;

                    Send(iq);

                }
                //if (iq.Type == IqType.set)
                //{
                //    Info setInfo = iq.SelectSingleElement(typeof(Info)) as Info;
                //    if (setInfo.Name == jid.User)
                //    {
                //        DatabaseDataSet databaseDataSet = new DatabaseDataSet();
                //        usersTableAdapter.Update_userInfo(setInfo.Pwd, setInfo.FaceId, setInfo.Sex, setInfo.Age, setInfo.Tel, setInfo.Email, setInfo.Name);
                //        usersTableAdapter.Update(databaseDataSet.users);
                //        //修改成功
                //    }
                //}
            }
            #endregion

            if (iq.Query != null)
            {
                #region 路由视频聊天请求
                if (iq.Query.GetType() == typeof(Rpc))
                {
                    iq.From = this.jid;
                    foreach (XmppSeverConnection con in Online.onlineuser)
                    {
                        if (con.jid.User == iq.To.User)
                        {
                            con.Send(iq);
                        }
                    }
                }
                #endregion

                #region 路由语音聊天请求
                else if (iq.Query.GetType() == typeof(Oob))
                {
                    iq.From = this.jid;
                    foreach (XmppSeverConnection con in Online.onlineuser)
                    {
                        if (con.jid.User == iq.To.User)
                        {
                            con.Send(iq);
                        }
                    }
                }
                #endregion

                #region 路由文件传输
                else if (iq.Query.GetType() == typeof(Last))
                {
                    iq.From = this.jid;
                    foreach (XmppSeverConnection con in Online.onlineuser)
                    {
                        if (con.jid.User == iq.To.User)
                        {
                            con.Send(iq);
                        }
                    }
                }
                #endregion

                #region 处理用户认证
                else if (iq.Query.GetType() == typeof(Auth))
                {
                    Auth auth = iq.Query as Auth;
                    switch (iq.Type)
                    {
                        case IqType.get:
                            iq.SwitchDirection();
                            iq.Type = IqType.result;
                            auth.AddChild(new Element("password"));
                            auth.AddChild(new Element("digest"));
                            Send(iq);
                            break;
                        case IqType.set:
                            this.jid = new Jid(auth.Username, "localhost", "Resource");
                            //用户登陆认证
                            try
                            {
                                if (alluser.Count(p => p.UserNo == auth.Username) == 0)
                                {
                                    iq.SwitchDirection();
                                    iq.Type = IqType.error;
                                    iq.Query = null;
                                    Send(iq);
                                    return;
                                }
                                if (Online.onlineuser.Count(p => p.jid.User == auth.Username) == 0)
                                {
                                    Online.onlineuser.Add(this);
                                    int itemNumber = frm.listViewOnlineUser.Items.Count;
                                    string[] subItem0 = { auth.Username, m_Sock.RemoteEndPoint.ToString() };
                                    frm.listViewOnlineUser.Items.Insert(itemNumber, new ListViewItem(subItem0));
                                    iq.SwitchDirection();
                                    iq.Type = IqType.result;
                                    iq.Query = null;
                                    Send(iq);

                                }
                                else
                                {
                                    iq.SwitchDirection();
                                    iq.Type = IqType.error;
                                    iq.Query = null;
                                    Send(iq);
                                }
                            }
                            catch (Exception ee)
                            {
                            }
                            break;
                    }
                }
                #endregion

                #region 处理用户列表与在线用户的发送
                else if (iq.Query.GetType() == typeof(Roster))
                {
                    ProcessRosterIQ(iq);
                }
                #endregion

                #region 处理会议消息
                else if (iq.Query.GetType() == typeof(Browse))
                {
                    switch (iq.Type)
                    {
                        case IqType.get:
                            //加入会议室
                            foreach (Meeting meeting in Online.onlinemeeting)
                            {
                                if (meeting.jid.Equals(iq.To))
                                {
                                    if (iq.Query.Value == meeting.password)
                                    {
                                        iq.Type = IqType.result;
                                        iq.From = iq.To;
                                        this.Send(iq);


                                        //将会议中的参与者发给他
                                        Presence presence = new Presence();
                                        presence.Type = PresenceType.subscribe;
                                        foreach (Jid jd in meeting.userinmeeting)
                                        {
                                            presence.From = jd;
                                            this.Send(presence);
                                        }

                                        meeting.userinmeeting.Add(this.jid);
                                        //将他参与会议的消息发给所有会议中的参与者
                                        presence.From = this.jid;
                                        foreach (Jid jd2 in meeting.userinmeeting)
                                        {
                                            foreach (XmppSeverConnection con in Online.onlineuser)
                                            {
                                                if (jd2.Equals(con.jid))
                                                {
                                                    con.Send(presence);
                                                    break;
                                                }
                                            }
                                        }
                                    }
                                    else
                                    {
                                        iq.From = iq.To;
                                        iq.Type = IqType.error;
                                        this.Send(iq);
                                    }
                                    break;
                                }
                            }
                            break;

                        case IqType.set:
                            //建立会议室
                            Meeting meeting2 = new Meeting(iq.To, iq.Query.Value);
                            meeting2.userinmeeting.Add(this.jid);
                            Online.onlinemeeting.Add(meeting2);
                            //将新建的会议室通知所有人
                            Presence pre = new Presence();
                            pre.Type = PresenceType.probe;
                            pre.From = iq.To;

                            foreach (XmppSeverConnection con in Online.onlineuser)
                            {
                                con.Send(pre);
                            }
                            break;
                    }
                }
                #endregion
            }
        }

        private void ProcessRosterIQ(IQ iq)
        {
            if (iq.Type == IqType.get)
            {
                // 发送用户列表
                getRosterItem(iq);
                Send(iq);

                //发送所有在线人及在线会议室的消息给他
                Presence pre;
                pre = new Presence();
                pre.Show = ShowType.chat;
                foreach (XmppSeverConnection con in Online.onlineuser)
                {
                    pre.From = con.jid;
                    Send(pre);
                }
                //将他在线消息发给所有在线人
                Presence pre1 = new Presence();
                pre1.Type = PresenceType.probe;
                foreach (Meeting meeting in Online.onlinemeeting)
                {
                    pre1.From = meeting.jid;
                    Send(pre1);
                }
            }
        }
        /*************************************************************
        * 2007-05-16   牛坤
        * 查询DataSet  即  得到用户列表   发送个登陆用户
        * 
        *用户登录验证 
        *************************************************************/
        #region  得到用户列表


        private IQ getRosterItem(IQ iq)
        {

            iq.SwitchDirection();
            iq.Type = IqType.result;
            foreach (var user in alluser)
            {
                RosterItem ri = new RosterItem();
                ri.Name = user.UserNo;
                ri.Subscription = SubscriptionType.both;
                ri.Jid = new Jid(ri.Name + "@localhost");
                ri.AddGroup(user.Depname);
                ri.Value = user.FaceID.ToString();
                iq.Query.AddChild(ri);
            }


            return iq;
        }
        #endregion
        private void SendOpenStream()
        {
            // Send the Opening Strem to the client
            string ServerDomain = "localhost";

            this.SessionId = Server.SessionId.CreateNewId();


            StringBuilder sb = new StringBuilder();

            sb.Append("<stream:stream from='");
            sb.Append(ServerDomain);

            sb.Append("' xmlns='");
            sb.Append(agsXMPP.Uri.CLIENT);

            sb.Append("' xmlns:stream='");
            sb.Append(agsXMPP.Uri.STREAM);

            sb.Append("' id='");
            sb.Append(this.SessionId);

            sb.Append("'>");

            Send(sb.ToString());
        }

        private void Send(Element el)
        {
            Send(el.ToString());
        }
    }
}
